#include "MS_Comm.h"
#include "easylogging++.h"
#include <thread>//sleep
#include <termio.h> //scankey
#include <unistd.h> //scankey
#include <signal.h> //ctrl+c

#ifndef InitEASYLOG
#define InitEASYLOG
    INITIALIZE_EASYLOGGINGPP //日志功能初始化、静态变量初始化，所以必须放在主函数之外
#endif

el::Logger* DataLogger = el::Loggers::getLogger("default");
bool EndThread = false;
MasterSlave_RW m_MSRW;//生成一个对象

// 设置日志系统
static void SetEasyLoggingConf(void)
{
    // 使用默认配置  
    el::Configurations myLoggingConf;  
    myLoggingConf.setToDefault();
    myLoggingConf.setGlobally(el::ConfigurationType::ToFile, "true");
    myLoggingConf.setGlobally(el::ConfigurationType::PerformanceTracking, "false");
    myLoggingConf.set(el::Level::Trace, el::ConfigurationType::Enabled, "false");
    myLoggingConf.set(el::Level::Debug, el::ConfigurationType::Filename, "dataLog/myLog_%datetime{%Y%M%d_%H%m%s_%g}_debug.log");
    myLoggingConf.set(el::Level::Error, el::ConfigurationType::Filename, "dataLog/myLog_%datetime{%Y%M%d_%H%m%s_%g}_error.log");
    myLoggingConf.set(el::Level::Fatal, el::ConfigurationType::Enabled, "false");//禁用
    myLoggingConf.set(el::Level::Warning, el::ConfigurationType::Enabled, "false");//禁用
    // myLoggingConf.set(el::Level::Warning, el::ConfigurationType::Filename, "dataLog/myLog_%datetime{%Y%M%d_%H%m%s_%g}_warning.log");
    myLoggingConf.set(el::Level::Info, el::ConfigurationType::Filename, "dataLog/myLog_%datetime{%Y%M%d_%H%m%s_%g}_info.log");
    myLoggingConf.set(el::Level::Verbose, el::ConfigurationType::Enabled, "false");//禁用
    el::Loggers::reconfigureAllLoggers(myLoggingConf);
	LOG(DEBUG)   << "***** debug log  *****";
	LOG(ERROR)   << "***** error log  *****";
	LOG(INFO)    << "***** info log  *****";
}

int scanKeyboard(void)
{
    int in;
    struct termios new_settings;
    struct termios stored_settings;
    tcgetattr(STDIN_FILENO,&stored_settings); //获得stdin 输入
    new_settings = stored_settings;           //
    new_settings.c_lflag &= (~ICANON);        //
    new_settings.c_cc[VTIME] = 0;
    tcgetattr(STDIN_FILENO,&stored_settings); //获得stdin 输入
    new_settings.c_cc[VMIN] = 1;
    tcsetattr(STDIN_FILENO,TCSANOW,&new_settings); //
    in = getchar();
    tcsetattr(STDIN_FILENO,TCSANOW,&stored_settings);
    return in;
}

void stopSys_cb(int s)
{
    EndThread = true;//退出线程
    std::cout<<std::endl<<"exit!!!"<<std::endl;
    exit(0); //终止程序
}

void scanKey_cb(void)
{
    LOG(DEBUG) << "scanKey_cb : Begin thread!";
    LOG(DEBUG) << "请输入\n\ta: 向下位机发送被攻击信号!\n" << "\tv: 读取接收到的下位机的电压\n" << "\tr: 读取到下位发送的炮塔旋转角度 \n" << "\ts: 向下位机发送前车灯控制信号，被攻击1次";
    while (!EndThread)
    {
        int key = scanKeyboard();
        switch (key)
        {
        case 'a': //向下位发送被攻击信号
            LOG(DEBUG) << " 向下位机发送被攻击信号!";
            m_MSRW.SendBeHidSignal();//发送被攻击信号
            break;
        case 'v': //打印下位发送的电压
            LOG(DEBUG) << " 读取下位机发送的电压为：" << m_MSRW.ReadBAT();
            break;
        case 'r': //打印下位机发送的炮塔旋转信号
            LOG(DEBUG) << " 读取到下位发送的炮塔旋转角度为：" << m_MSRW.ReadTurretAngle();
            break;
        case 's':
            LOG(DEBUG) << " 向下位机发送前车灯控制信号，被攻击1次";
            m_MSRW.SetLightStat(MasterSlave_RW::LS_BeHid_1);            
            break;
        default:
            break;
        }
        //LOG(DEBUG)<<key;
        std::this_thread:: sleep_for (std::chrono::milliseconds (100));//10ms
    }
    LOG(DEBUG) << "scanKey_cb : End thread!";
    return ;
}

int main()
{
    SetEasyLoggingConf();//初始化日志配置
    /*处理ctrl+C*/
    struct sigaction sigIntHandler;
    sigIntHandler.sa_handler =  stopSys_cb;
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGINT,&sigIntHandler,NULL);

    LOG(INFO) << "Main : begin Read config!";

    m_MSRW.init();//初始化

    LOG(INFO) << "Main : begin scanKey_cb thread.";
    std::thread scanKeyThread(scanKey_cb);
    LOG(INFO) << "Main : scanKey_cb thread detach!";
    scanKeyThread.detach();

    while (true)
    {
        std::this_thread:: sleep_for (std::chrono::seconds (60));
    }
    return 0;
}